/* ================================================================================
//	Crypteviant!
//	Providing tough encrypted P2P Chat
//	Copyright (C) 2010  Martin Pfeifer, Tobias Rausch
//
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ============================================================================== */

#include "sha512.hpp"

using namespace Hash;

Sha512::Sha512()
    : AbstractHash()
{
    reset();
}


Sha512::~Sha512()
{
}


void Sha512::update(const QString data)
{
    // Put the QString data into an std::string and convert to byte array
    std::string input = data.toAscii().constData();
    byte const * inputArray = new byte[input.length()];
    inputArray = (byte const*) input.c_str();

    // Hash the data
    m_hash.Update(inputArray, input.length());
}


QString Sha512::hash()
{
    // Reserve space for digest and generate it finally
    byte digest[CryptoPP::SHA512::DIGESTSIZE] = {0};
    m_hash.Final(digest);

    byte *hash = encodeHex(digest, CryptoPP::SHA512::DIGESTSIZE);
    QString hash_1 = (char*) hash;

    // Second iteration
    QString hash_2 = generateHash(hash_1);

    return hash_2;
}


QString Sha512::generateHash(QString &data) const
{
    CryptoPP::SHA512 hash;

    // Put the QString data into an std::string and convert to byte array
    std::string input = data.toAscii().constData();
    byte const * inputArray = new byte[input.length()];
    inputArray = (byte const*) input.c_str();

    // Hash the given SHA512 hash again (second iteration)
    byte digest[CryptoPP::SHA512::DIGESTSIZE] = {0};
    hash.CalculateDigest(digest, inputArray, input.length());

    QString hashVal = (char*) encodeHex(digest, CryptoPP::SHA512::DIGESTSIZE);

    return hashVal;
}


void Sha512::reset()
{
    m_hash.Restart();
}


byte *Sha512::encodeHex(byte input[], int length) const
{
    CryptoPP::HexEncoder hex;

    byte *hashVal = NULL;
    hashVal = new byte[(length * 2) + 1];
    hex.Put(input, length);
    hex.Get(hashVal, (length * 2) + 1);

    hashVal[length * 2] = '\0';
    return hashVal;
}


int Sha512::optimalBlockSize() const
{
    return m_hash.OptimalBlockSize();
}
